package org.com.fw.web.security;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.com.fw.consts.FwConst;
import org.com.fw.util.AppUtil;
import org.com.fw.util.StringUtil;
import org.com.mars.service.system.SysAuthorityResourceService;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;

public class MarsSecurityMetadataSource implements FilterInvocationSecurityMetadataSource, BeanPostProcessor {

	// 例外url
	private HashSet<String> anonymousUrls = new HashSet<String>();

	@Override
	public Collection<ConfigAttribute> getAllConfigAttributes() {
		return null;
	}

	@Override
	public Collection<ConfigAttribute> getAttributes(Object arg0) throws IllegalArgumentException {

		// 将这个url资源拥有的权限全部取出
		Collection<ConfigAttribute> configAttributes = new HashSet<ConfigAttribute>();

		FilterInvocation filterInvocation = (FilterInvocation) arg0;
		HttpServletRequest request = filterInvocation.getRequest();

		// 请求URL
		String url = request.getRequestURI();
		url = removeCtx(url, request.getContextPath());

		// 如果是URL匿名
		if (this.anonymousUrls.contains(url)) {
			// 加入匿名权限
			configAttributes.add(FwConst.ROLE_CONFIG_ANONYMOUS);
			return configAttributes;
		}

		// 通过资源表，资源权限表，权限表，取出该资源对应的所有权限
		SysAuthorityResourceService sysAuthorityResourceService = (SysAuthorityResourceService) AppUtil
				.getBean(SysAuthorityResourceService.class);
		List<String> authoritiesByUrl = sysAuthorityResourceService.getAuthoritiesByUrl(url);
		if (authoritiesByUrl != null && !authoritiesByUrl.isEmpty()) {
			for (String authority : authoritiesByUrl) {
				ConfigAttribute configAttribute = new SecurityConfig(authority);
				configAttributes.add(configAttribute);
			}
		} else {
			configAttributes.add(FwConst.ROLE_CONFIG_PUBLIC);
		}

		return configAttributes;
	}

	@Override
	public boolean supports(Class<?> arg0) {
		return true;
	}

	@Override
	public Object postProcessAfterInitialization(Object arg0, String arg1) throws BeansException {
		return arg0;
	}

	@Override
	public Object postProcessBeforeInitialization(Object arg0, String arg1) throws BeansException {
		return arg0;
	}

	/**
	 * 取得相对url
	 * 
	 * @param url
	 * @param contextPath
	 * @return
	 */
	private static String removeCtx(String url, String contextPath) {
		url = url.trim();
		if (StringUtil.isEmpty(contextPath)) {
			return url;
		} else if (StringUtil.isEmpty(url)) {
			return "";
		} else if (url.startsWith(contextPath)) {
			url = url.replaceFirst(contextPath, "");
		}
		return url;
	}

	/**
	 * 例外url设定
	 * 
	 * @param anonymousUrls
	 */
	public void setAnonymousUrls(HashSet<String> anonymousUrls) {
		this.anonymousUrls = anonymousUrls;
	}

}
